package com.github.binarywang.demo.wx.cp.controller;

import cn.hutool.core.lang.Pair;
import com.alibaba.fastjson.JSONObject;
import com.demo.third.ThirdAuthenticationDemo;
import com.github.binarywang.demo.wx.cp.aes.*;
import com.github.binarywang.demo.wx.cp.constant.ChangeTypeEnum;
import com.github.binarywang.demo.wx.cp.constant.InfoTypeEnum;
import com.github.binarywang.demo.wx.cp.constant.WxCpConstant;
import com.github.binarywang.demo.wx.cp.error.BizException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Objects;

/**
 * created by lanxinghua@2dfire.com on 2020/2/14
 * 企业微信第三方应用开发
 */
@RestController
public class ThirdTestController extends ThirdBaseController{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 数据回调url，一般用不上
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @RequestMapping("/callback/data")
    public String data(@RequestParam(name = "msg_signature", required = false) String signature,
                       @RequestParam(name = "timestamp", required = false) String timestamp,
                       @RequestParam(name = "nonce", required = false) String nonce,
                       @RequestParam(name = "echostr", required = false) String echostr) {
        logger.info("数据回调");
        logger.info("signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]", signature, timestamp, nonce, echostr);
        String sEchoStr; //需要返回的明文
        if (StringUtils.isEmpty(echostr)){
            return "success";
        }
        try {
            sEchoStr = verifyUrl(signature, timestamp, nonce, echostr);
            System.out.println("verifyurl echostr: " + sEchoStr);
            return sEchoStr;
        } catch (Exception e) {
            //验证URL失败，错误原因请查看异常
            e.printStackTrace();
        }
        return "fail";
    }


    /**
     * 指令回调url  通讯录，部门变更，  授权变更，  ticket数据
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @param request
     * @param response
     * @return
     * @throws AesException
     * @throws IOException
     */
    @RequestMapping(value = "/suite/receive")
    public String suite(@RequestParam("msg_signature") String signature,
                        @RequestParam("timestamp") String timestamp,
                        @RequestParam("nonce") String nonce,
                        @RequestParam(value = "echostr", required = false) String echostr,
                        HttpServletRequest request,
                        HttpServletResponse response) throws Exception {
        logger.info("指令回调URL-调用我了");
        logger.info("signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]", signature, timestamp, nonce, echostr);

        // echostr不为空为回调配置请求
        if (null != echostr) {
            return verifyUrl(signature, timestamp, nonce, echostr);
        }

        BufferedReader reader = request.getReader();
        StringBuffer buffer = new StringBuffer();
        String line = " ";
        while (null != (line = reader.readLine())) {
            buffer.append(line);
        }
        String postData = buffer.toString();
        System.out.println("postData:" + postData);
        // reciveId为应用的suiteId
        wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, "ww141f5c1b0bfe0bc2");
        String decryptMsgs = null;
        try {
            decryptMsgs = wxcpt.DecryptMsg(signature, timestamp, nonce, postData);
            System.out.println("解密后的xml数据:" + decryptMsgs);
        }catch (AesException e){
            logger.error("签名错误： signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]", signature, timestamp, nonce, echostr);
            return "success";
        }
        Pair<String, org.json.JSONObject> type = doType(decryptMsgs);
        InfoTypeEnum infoTypeEnum = InfoTypeEnum.getByInstance(type.getKey());
        if (infoTypeEnum == null){
            throw new Exception("不支持该类型操作");
        }
        org.json.JSONObject jsonObject = type.getValue();
        switch (infoTypeEnum){
            case SUITE_TICKET:{
                //（每十分钟）推送ticket。ticket会实时变更，并用于后续接口的调用。
                String suiteAccessToken = getSuiteAccessToken();
                if (suiteAccessToken != null){
                    logger.info("推送ticket成功，suiteAccessToken未过期");
                    break;
                }
                logger.info("推送ticket成功，suiteAccessToken过期，重新获取");
                getSuiteToken(jsonObject);
                break;
            }
            // 企业微信应用市场发起授权时，企业微信后台会推送授权成功通知
            case CREATE_AUTH:{
                logger.info("创建授权：" + jsonObject.toString());
                String suiteId = jsonObject.get("SuiteId").toString();
                String authCode = jsonObject.get("AuthCode").toString();
                String timeStamp = jsonObject.get("TimeStamp").toString();
                String permanentCode = getPermanentCode(getSuiteAccessToken(), authCode);
                logger.info("永久授权码：" + permanentCode);
                break;
            }
            case CHANGE_AUTH:{
                logger.info("变更授权");
                // TODO: 2020/2/14
                break;
            }
            case CHANGE_CONTACT:{
                logger.info("通讯录变更");
                String changeType = jsonObject.getString(WxCpConstant.CHANGE_TYPE);
                ChangeTypeEnum changeTypeEnum = ChangeTypeEnum.getByInstance(changeType);
                if (Objects.isNull(changeTypeEnum)){
                    throw new Exception("该类型通讯录变更不存在");
                }
                switch (changeTypeEnum){
                    case DELETE_USER:{
                        logger.info("删除用户");
                        break;
                    }
                    case UPDATE_TAG:{
                        logger.info("更新标签");
                        break;
                    }
                    case DELETE_PARTY:{
                        logger.info("删除部门");
                        break;
                    }
                    default:{
                        break;
                    }
                }
                break;
            }
            case CHANGE_EXTERNAL_CONTACT:{
                logger.info("外部联系人");
                String changeType = jsonObject.getString(WxCpConstant.CHANGE_TYPE);
                ChangeTypeEnum changeTypeEnum = ChangeTypeEnum.getByInstance(changeType);
                if (Objects.isNull(changeTypeEnum)){
                    throw new Exception("该类型CHANGE_EXTERNAL_CONTACT不存在");
                }
                switch (changeTypeEnum){
                    case ADD_EXTERNAL_CONTACT:{
                        logger.info("添加客户" + jsonObject.toString());
                        String externalUserID = jsonObject.get("ExternalUserID").toString();
                        String welcomeCode = jsonObject.get("WelcomeCode").toString();
                        String userID = jsonObject.get("UserID").toString();
                        String suiteId = jsonObject.get("SuiteId").toString();
                        String authCorpId = jsonObject.get("AuthCorpId").toString();
                        System.out.println("欢迎code：" + welcomeCode);
                        sendWelcome(getAccessToken(true), welcomeCode);
                        break;
                    }
                    default:{
                        break;
                    }
                }
            }
            default:{
                break;
            }
        }
        return "success";
    }


    /**
     * 通过code授权
     * @param code
     * @param state
     * @throws Exception
     */
    @RequestMapping("/oauth")
    public void oauthCode(@RequestParam(name = "code") String code,
                          @RequestParam(name = "state") String state,
                          HttpServletResponse response
                          ) throws Exception{
        System.out.println("业务设置URL-微信调用我了");
        logger.info("code = [{}]  state = [{}]", code, state);
        if (StringUtils.isBlank(code)){
            throw new Exception("code为空");
        }
        JSONObject userInfo = ThirdAuthenticationDemo.getUserInfo3rd(code);
        // 成员票据
        String user_ticket = userInfo.getString("user_ticket");
        // 用户所属企业的corpId
        String corpId = userInfo.getString("CorpId");
        // 在企业内的UserID
        String userId = userInfo.getString("UserId");

        /*JSONObject userDetail = ThirdAuthenticationDemo.getUserDetail3rd(user_ticket);
        String name = userDetail.getString("name");
        String sex = userDetail.getString("gender");
        String avatar = userDetail.getString("avatar");
        String department = userDetail.getString("department");*/
        String token = userId + ":" + corpId;
        if (state.contains("?")){
            state = state + "&token=" + token;
        }else {
            state = state + "?token=" + token;
        }
        response.sendRedirect(state);
    }


    /**
     * 商家扫码授权回调处理
     * @param authCode
     * @param expiresIn
     * @param entityId
     * @return
     */
    @RequestMapping("/callback/oauth")
    public void callbackOauth(@RequestParam(name = "auth_code") String authCode,
                              @RequestParam(name = "expires_in", required = false) String expiresIn,
                              @RequestParam(name = "state", required = false) String entityId) throws Exception{
        logger.info("商家扫码授权回调处理");
        logger.info("authCode = [{}], entityId = [{}]", authCode, entityId);
        if (StringUtils.isBlank(authCode)){
            throw new Exception("商家扫码授权回调处理失败");
        }

        // 获取永久授权码
        String suiteAccessToken = getSuiteAccessToken();
        String permanentCode = getPermanentCode(suiteAccessToken, authCode);
        if (StringUtils.isBlank(permanentCode)) {
            throw new Exception("永久授权码获取失败");
        }

        // 获取到授权信息
        JSONObject jsonObject = getAuthInfo(suiteAccessToken, sCorpID, permanentCode);
        System.out.println(jsonObject.toJSONString());
        System.out.println("保存授权信息，授权成功.........");
    }


    public static void main(String[] args) throws Exception{
        //System.out.println(getOpenId(accessToken, "ChenXingXing"));
        // getCoperInfo(getAccessToken(), "ChenXingXing");
        // 获取预授权码;
        // System.out.println(getPreAuthToken(getSuiteAccessToken()));
        // sendWelcome(getAccessToken(true), "RCimKx8bGBHIPYjnjEUIuCWBe4Y7infal8i9R3jGBr4");

        getPermanentCode(getSuiteAccessToken(), "DgbUGH3qo3lMq7ej2sJ2Y_2VCvBbDx79SddBDc0pT6A");
    }

}
